GDK-Win32: Fix glitches when using EGL/ANGLE
authorChun-wei Fan <fanc999@yahoo.com.tw>
Tue, 22 May 2018 10:05:35 +0000 (18:05 +0800)
committerChun-wei Fan <fanchunwei@src.gnome.org>
Thu, 28 Jun 2018 07:33:42 +0000 (15:33 +0800)
We need to force redraws of the whole window when we are using EGL/ANGLE
during maximize, restore and Aerosnap ops so that we do not get glitches
in the resulting window.

gdk/win32/gdkevents-win32.c
gdk/win32/gdkglcontext-win32.c
gdk/win32/gdkglcontext-win32.h
gdk/win32/gdkwindow-win32.c
gdk/win32/gdkwindow-win32.h

index a2cd67cf038d43bcc730c2e65c32f296080f9e99..f153dcba3d3f0c1113e13324753f5f06c4e963a2 100644 (file)
@@ -93,6 +93,8 @@
  * Private function declarations
  */
 
+extern void _gdk_win32_window_invalidate_egl_framebuffer (GdkWindow *window);
+
 #define SYNAPSIS_ICON_WINDOW_CLASS "SynTrackCursorWindowClass"
 
 static gboolean gdk_event_translate (MSG        *msg,
@@ -3248,6 +3250,9 @@ gdk_event_translate (MSG  *msg,
        case SC_MINIMIZE:
        case SC_RESTORE:
          do_show_window (window, msg->wParam == SC_MINIMIZE ? TRUE : FALSE);
+
+    if (msg->wParam == SC_RESTORE)
+      _gdk_win32_window_invalidate_egl_framebuffer (window);
          break;
         case SC_MAXIMIZE:
           impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
index 7a6ff8ee5a77696388fcc7e4c5acea1443e0487f..26a8b02a6aa6ba38ab8cebbf0f46dafcbc9c200f 100644 (file)
@@ -141,6 +141,35 @@ gdk_gl_blit_region (GdkWindow *window, cairo_region_t *region)
     }
 }
 
+static gboolean
+_get_is_egl_force_redraw (GdkWindow *window)
+{
+  /* We only need to call gdk_window_invalidate_rect () if necessary */
+#ifdef GDK_WIN32_ENABLE_EGL
+  if (window->gl_paint_context != NULL && gdk_gl_context_get_use_es (window->gl_paint_context))
+    {
+      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+      return impl->egl_force_redraw_all;
+    }
+#endif
+  return FALSE;
+}
+
+static void
+_reset_egl_force_redraw (GdkWindow *window)
+{
+#ifdef GDK_WIN32_ENABLE_EGL
+  if (window->gl_paint_context != NULL && gdk_gl_context_get_use_es (window->gl_paint_context))
+    {
+      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+      if (impl->egl_force_redraw_all)
+        impl->egl_force_redraw_all = FALSE;
+    }
+#endif
+}
+
 void
 _gdk_win32_gl_context_end_frame (GdkGLContext *context,
                                  cairo_region_t *painted,
@@ -173,7 +202,6 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
             }
         }
 
-      /* EGL does not have do_blit_swap */
       if (context_win32->do_blit_swap)
         {
           glDrawBuffer(GL_FRONT);
@@ -193,6 +221,21 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
   else
     {
       EGLSurface egl_surface = _gdk_win32_window_get_egl_surface (window, context_win32->egl_config, FALSE);
+      gboolean force_egl_redraw_all = _get_is_egl_force_redraw (window);
+
+      if (context_win32->do_blit_swap && !force_egl_redraw_all)
+        gdk_gl_blit_region (window, painted);
+      else if (force_egl_redraw_all)
+        {
+          GdkRectangle rect = {0, 0, gdk_window_get_width (window), gdk_window_get_height (window)};
+
+          /* We need to do gdk_window_invalidate_rect() so that we don't get glitches after maximizing or
+           *  restoring or using aerosnap
+           */
+          gdk_window_invalidate_rect (window, &rect, TRUE);
+          _reset_egl_force_redraw (window);
+        }
+
       eglSwapBuffers (display->egl_disp, egl_surface);
     }
 #endif
@@ -214,7 +257,6 @@ _gdk_win32_window_invalidate_for_new_frame (GdkWindow *window,
   context_win32 = GDK_WIN32_GL_CONTEXT (window->gl_paint_context);
   context_win32->do_blit_swap = FALSE;
 
-  /* gdk_gl_context_has_framebuffer_blit() is for Desktop GL only ! */
   if (gdk_gl_context_has_framebuffer_blit (window->gl_paint_context) &&
       cairo_region_contains_rectangle (update_area, &whole_window) != CAIRO_REGION_OVERLAP_IN)
     {
@@ -1309,3 +1351,20 @@ gdk_win32_display_get_wgl_version (GdkDisplay *display,
 
   return TRUE;
 }
+
+void
+_gdk_win32_window_invalidate_egl_framebuffer (GdkWindow *window)
+{
+/* If we are using ANGLE, we need to force redraw of the whole Window and its child windows
+ *  as we need to re-acquire the EGL surfaces that we rendered to upload to Cairo explicitly,
+ *  using gdk_window_invalidate_rect (), when we maximize or restore or use aerosnap
+ */
+#ifdef GDK_WIN32_ENABLE_EGL
+  if (window->gl_paint_context != NULL && gdk_gl_context_get_use_es (window->gl_paint_context))
+    {
+      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+      impl->egl_force_redraw_all = TRUE;
+    }
+#endif
+}
index f5535823f20ec67b0e7b2c0575a10c8b84e038f7..d58760ce6382a63c82cc797a705fd60ea870a87c 100644 (file)
@@ -86,6 +86,9 @@ gboolean
 _gdk_win32_gl_context_realize (GdkGLContext *context,
                                GError **error);
 
+void
+_gdk_win32_window_invalidate_egl_framebuffer (GdkWindow *window);
+
 G_END_DECLS
 
 #endif /* __GDK_WIN32_GL_CONTEXT__ */
index 2fd6ef2c5c123af56e820758fba9c4e8c11badd5..3535859194fde7f3ce5be5d0a4a67dc10b5102c7 100644 (file)
@@ -1701,6 +1701,8 @@ gdk_win32_window_move_resize (GdkWindow *window,
   window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
   window_impl->inhibit_configure = TRUE;
 
+  _gdk_win32_window_invalidate_egl_framebuffer (window);
+
   /* We ignore changes to the window being moved or resized by the
      user, as we don't want to fight the user */
   if (GDK_WINDOW_HWND (window) == _modal_move_resize_window)
@@ -5275,6 +5277,8 @@ gdk_win32_window_maximize (GdkWindow *window)
                           GDK_WINDOW_HWND (window),
                           _gdk_win32_window_state_to_string (window->state)));
 
+  _gdk_win32_window_invalidate_egl_framebuffer (window);
+
   if (GDK_WINDOW_IS_MAPPED (window))
     GtkShowWindow (window, SW_MAXIMIZE);
   else
@@ -5295,6 +5299,8 @@ gdk_win32_window_unmaximize (GdkWindow *window)
                           GDK_WINDOW_HWND (window),
                           _gdk_win32_window_state_to_string (window->state)));
 
+  _gdk_win32_window_invalidate_egl_framebuffer (window);
+
   if (GDK_WINDOW_IS_MAPPED (window))
     GtkShowWindow (window, SW_RESTORE);
   else
@@ -6034,6 +6040,8 @@ GtkShowWindow (GdkWindow *window,
     case SW_SHOWNA:
     case SW_SHOWNOACTIVATE:
     case SW_SHOWNORMAL:
+      _gdk_win32_window_invalidate_egl_framebuffer (window);
+
       if (IsWindowVisible (hwnd))
         break;
 
index a5e837ec8ddeeaf25d64c76cd7f5c94dd5f8ecfd..e1ef92096dbfcaba285920888824adfabb7b3376 100644 (file)
@@ -360,6 +360,7 @@ struct _GdkWindowImplWin32
 #ifdef GDK_WIN32_ENABLE_EGL
   EGLSurface egl_surface;
   EGLSurface egl_dummy_surface;
+  guint egl_force_redraw_all : 1;
 #endif
 };